package com.xj.config;

import cn.hutool.core.date.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Range;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.strategy.sharding.StandardShardingStrategyConfiguration;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;

import java.util.*;

/**
 * @author ricky
 * @date 2022/9/13
 */
@Slf4j
public class YhStandardShardingAlgorithm extends BaseStandardShardingAlgorithm<Date> {

    public static final String TYPE = "YhStandardShardingAlgorithm";

    private static final String FORMAT = "_yyyyMM";

    private static final String TABLE_NAME = "t_yhgl_xt_yh";
    private static final String COLUMN_NAME = "zcsj";
    private static final String ACTUAL_DATA_NODES = "ds.t_yhgl_xt_yh_${2020..2024}0${1..9},ds.t_yhgl_xt_yh_${2020..2024}1${0..2}";

    public static ShardingTableRuleConfiguration getShardingTableRuleConfig() {

        // 配置表规则
        ShardingTableRuleConfiguration recordTableRuleConfiguration = new ShardingTableRuleConfiguration(TABLE_NAME, ACTUAL_DATA_NODES);
        // 配置分表策略
        recordTableRuleConfiguration.setTableShardingStrategy(new StandardShardingStrategyConfiguration(COLUMN_NAME, TYPE));

        return recordTableRuleConfiguration;
    }

    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<Date> shardingValue) {
        StringBuilder tableName = new StringBuilder();
        Date startTime = shardingValue.getValue();

        log.info("执行操作的表名{}", shardingValue.getLogicTableName() + DateUtil.format(startTime, FORMAT));
        tableName.append(shardingValue.getLogicTableName()).append(DateUtil.format(startTime, FORMAT));

        checkTable(tableName.toString());
        System.out.println("返回表名：" + tableName);
        return tableName.toString();
    }

    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Date> rangeShardingValue) {
        Collection<String> result = new LinkedHashSet<>();

        Range<Date> shardingKey = rangeShardingValue.getValueRange();

        Date startTime = shardingKey.lowerEndpoint();

        Date endTime = shardingKey.upperEndpoint();

        // 获取起始，终止时间范围
        Date now = new Date();
        if (startTime.after(now)) {
            startTime = now;
        }
        if (endTime.after(now)) {
            endTime = now;
        }
        Collection<String> tables = getRoutTable(rangeShardingValue.getLogicTableName(), startTime, endTime);

        if (tables.size() > 0) {
            result.addAll(tables);
        }
        return result;
    }

    private Collection<String> getRoutTable(String logicTableName, Date startTime, Date endTime) {
        Set<String> rouTables = new HashSet<>();
        if (startTime != null && endTime != null) {
            List<String> rangeNameList = getRangeNameList(startTime, endTime);
            for (String yearMonth : rangeNameList) {
                String tableName = logicTableName + yearMonth;
                checkTable(tableName);
                rouTables.add(tableName);
            }
        }
        return rouTables;
    }

    private static List<String> getRangeNameList(Date startTime, Date endTime) {
        List<String> result = Lists.newArrayList();

        DateTime beginOfMonth = DateUtil.beginOfMonth(startTime);
        DateTime endOfMonth = DateUtil.beginOfMonth(endTime);


        while (beginOfMonth.getTime() <= endOfMonth.getTime()) {
            result.add(DateUtil.format(beginOfMonth, FORMAT));
            // 进行当前日期按月份 + 1
            beginOfMonth = beginOfMonth.offset(DateField.MONTH, 1);
        }
        return result;
    }

    @Override
    public String getType() {
        return TYPE;
    }

    @Override
    String getTableName() {
        return TABLE_NAME;
    }
}
